﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using LitJson;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using static DMC300Axis_IO.Function.DMC300_Info;
using System.Runtime.InteropServices.ComTypes;
using MvCameraControl;
using OCR.Config;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using OCR.SystemThread;
using OCR.SettingsForm;

namespace OCR
{
    class AlgorithmModule_GPU
    {
        [DllImport(@"ocr_v4_gpu.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void CreateInstance();
        [DllImport(@"ocr_v4_gpu.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr do_ocr_Mat(IntPtr img);
        [DllImport(@"ocr_v4_gpu.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr do_ocr(byte[] imageData, int width, int height);
        [DllImport(@"ocr_v4_gpu.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void DestroyInstance();

        public static List<List<Point>> pointsList = new List<List<Point>>();
        public static List<TemplateConfig_GPU> currConfigs = new List<TemplateConfig_GPU>();
        public static List<List<Point>> convertList = new List<List<Point>>();


        public static List<string> mainInfos = new List<string>();
        public static List<List<Point>> finalPointList = new List<List<Point>>();

        public static DateTime dt1;
        public static DateTime dt2;
        public static string dt1_dt2_time;

        #region opencv
        public static OpenCvSharp.Mat ByteToMat_m1(byte[] Picture, int a, int b)
        {
            OpenCvSharp.Mat imageData = new OpenCvSharp.Mat(a, b, OpenCvSharp.MatType.CV_8UC3);
            int length = Picture.Length;// mats.Rows * mats.Cols * 3;
            Marshal.Copy(Picture, 0, imageData.Data, length);
            return imageData;
        }
        public static void TestImgOpencv(string path)
        {
            OpenCvSharp.Mat src = OpenCvSharp.Cv2.ImRead(path, OpenCvSharp.ImreadModes.Color);
            if (src.Empty())
            {
                Console.WriteLine("无法加载图像，请检查路径是否正确。");
                return;
            }

            for (int i = 0; i < 100; i++)
            {
                IntPtr resultPtr = do_ocr_Mat(src.CvPtr);
                if (resultPtr != IntPtr.Zero) // 确保结果不为 null
                {
                    string result = Marshal.PtrToStringAnsi(resultPtr);
                    byte[] rebytes = Encoding.Default.GetBytes(result);
                    byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
                    result = Encoding.Default.GetString(bytes, 0, bytes.Length);
                    Console.WriteLine("OCR Result:\n" + result);
                }
                else
                {
                    Console.WriteLine("OCR processing failed or instance was not created.");
                }
            }
        }
        public static void ImageHandleV2_Opencv(string path)
        {
            pointsList.Clear();

            Console.WriteLine("OpenCvSharp");

            OpenCvSharp.Mat src = OpenCvSharp.Cv2.ImRead(path, OpenCvSharp.ImreadModes.Color);

            if (src.Empty())
            {
                Console.WriteLine("无法加载图像，请检查路径是否正确。");
                return;
            }
            dt1 = DateTime.Now;
            IntPtr resultPtr = do_ocr_Mat(src.CvPtr);
            dt2 = DateTime.Now;

            Console.WriteLine("dt2-dt1 "+(dt2-dt1).TotalMilliseconds);
            if (resultPtr == IntPtr.Zero)
                return;

            string result = Marshal.PtrToStringAnsi(resultPtr);

            byte[] rebytes = Encoding.Default.GetBytes(result);
            result = Encoding.UTF8.GetString(rebytes).Replace("end", "");



            JsonData jsonData = JsonMapper.ToObject(result);
            string finalResult = JsonMapper.ToJson(jsonData["results"]);
            Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

            List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
            configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

            configs = configs.Where(a => a.rec_score >= 0.3).ToList();

            for (int i = 0; i < configs.Count; i++)
            {
                configs[i].text = FilterWithLINQ(configs[i].text);
                Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);
                List<Point> points = new List<Point>();
                for (int j = 0; j < configs[i].box.Count; j++)
                {
                    Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                    points.Add(point);
                }
                pointsList.Add(points);
            }
            currConfigs = configs;

            MergeChar();

            //LocalCompare(pointsList);
        }
        public static Image ImageHandleV2_Opencv(Bitmap bitmap)
        {
            pointsList.Clear();

            Console.WriteLine("OpenCvSharp_bitmap");

            DateTime dt1 = DateTime.Now;

            MemoryStream ms = new MemoryStream();
            bitmap.Save(ms, ImageFormat.Jpeg);  // 支持PNG、BMP等格式
            byte[] bytes = ms.ToArray();
            ms.Dispose();
            OpenCvSharp.Mat src = OpenCvSharp.Mat.FromImageData(bytes);
            //OpenCvSharp.Mat src = ByteToMat_m1(bytes, bitmap.Width, bitmap.Height);
            //src.ImWrite("tempp1.bmp");
            if (src.Empty())
            {
                Console.WriteLine("无法加载图像，请检查路径是否正确。");
                return null;
            }

            IntPtr resultPtr = do_ocr_Mat(src.CvPtr);
            if (resultPtr == IntPtr.Zero)
                return null;
            DateTime dt2 = DateTime.Now;
            string result = Marshal.PtrToStringAnsi(resultPtr);

            byte[] rebytes = Encoding.Default.GetBytes(result);
            result = Encoding.UTF8.GetString(rebytes).Replace("end", "");


            JsonData jsonData = JsonMapper.ToObject(result);
            string finalResult = JsonMapper.ToJson(jsonData["results"]);
            Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

            List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
            configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

            configs = configs.Where(a => a.rec_score >= 0.3).ToList();

            for (int i = 0; i < configs.Count; i++)
            {                    
                //过滤'.',汉字，字母，空格 --
                configs[i].text = FilterWithLINQ(configs[i].text);
                Console.WriteLine("算法图片信息" + i + ": " + configs[i].text );//+ "-" + configs[i].rec_score + "-" + configs[i].cls_score + "-" + configs[i].cls_label
                List<Point> points = new List<Point>();
                for (int j = 0; j < configs[i].box.Count; j++)
                {
                    Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                    points.Add(point);
                }
                pointsList.Add(points);
            }
            currConfigs = configs;

            MergeChar();

            return bitmap;

        }
        public static Image ImageHandleV2_Opencv(Bitmap bitmap,bool isCompare)
        {
            pointsList.Clear();

            Console.WriteLine("OpenCvSharp_bitmap");

            DateTime dt1 = DateTime.Now;

            MemoryStream ms = new MemoryStream();
            bitmap.Save(ms, ImageFormat.Bmp);  // 支持PNG、BMP等格式
            byte[] bytes = ms.ToArray();
            ms.Dispose();
            OpenCvSharp.Mat src = OpenCvSharp.Mat.FromImageData(bytes,OpenCvSharp.ImreadModes.Color);

            if (src.Empty())
            {
                Console.WriteLine("无法加载图像，请检查路径是否正确。");
                return null;
            }

            IntPtr resultPtr = do_ocr_Mat(src.CvPtr);
            if (resultPtr == IntPtr.Zero)
                return null;
            DateTime dt2 = DateTime.Now;
            string result = Marshal.PtrToStringAnsi(resultPtr);

            byte[] rebytes = Encoding.Default.GetBytes(result);
            result = Encoding.UTF8.GetString(rebytes).Replace("end", "");


            JsonData jsonData = JsonMapper.ToObject(result);
            string finalResult = JsonMapper.ToJson(jsonData["results"]);
            Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

            List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
            configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

            for (int i = 0; i < configs.Count; i++)
            {
                Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);//+ "-" + configs[i].rec_score + "-" + configs[i].cls_score + "-" + configs[i].cls_label
                List<Point> points = new List<Point>();
                for (int j = 0; j < configs[i].box.Count; j++)
                {
                    Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                    points.Add(point);
                }
                pointsList.Add(points);
            }
            currConfigs = configs;

            if (isCompare)
            {
                LocalCompare(pointsList);
            }

            return bitmap;

        }

        public static void ImageHandleV2_CropImg(Bitmap originalImage, Rectangle cropArea, string outputCropPath = "")
        {
            DateTime dt_Crop_in = DateTime.Now;
            bool t1 = cropArea.Right > originalImage.Width;
            bool t2 = cropArea.Bottom > originalImage.Height;
            //Console.WriteLine("cropArea.X :" + cropArea.X + "  cropArea.Y :" + cropArea.Y
            //    + "  cropArea.Width :" + cropArea.Width + "  cropArea.Height :" + cropArea.Height
            //    + "  cropArea.Right :" + cropArea.Right + "  cropArea.Bottom :" + cropArea.Bottom
            //    + "  originalImage.Right :" + originalImage.Width + "  originalImage.Height :" + originalImage.Height
            //    + "  cropArea.Right > originalImage.Width：" + t1
            //    + "  cropArea.Bottom > originalImage.Height：" + t2);
            // 检查裁剪区域是否有效
            if (cropArea.X < 0 || cropArea.Y < 0 ||
                cropArea.Width <= 0 || cropArea.Height <= 0 ||
                cropArea.Right > originalImage.Width ||
                cropArea.Bottom > originalImage.Height)
            {
                Console.WriteLine("裁剪内部--裁剪区域无效");
                //return null;
                //throw new ArgumentException("Invalid crop area");
            }
            Console.WriteLine(cropArea.Size);
            // 创建目标位图
            var croppedImage = new Bitmap(cropArea.Width, cropArea.Height);
            // 创建绘图对象
            var graphics = Graphics.FromImage(croppedImage);

            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            graphics.CompositingQuality = CompositingQuality.HighQuality;
            // 绘制裁剪区域
            graphics.DrawImage(
                originalImage,
                new Rectangle(0, 0, croppedImage.Width, croppedImage.Height),
                cropArea,
                GraphicsUnit.Pixel
            );
            DateTime dt_Crop_out = DateTime.Now;
            //originalImage.Dispose();
            Bitmap bitmap = ConvertTo8bpp(croppedImage);
            if (outputCropPath != "")
            {
                //Console.WriteLine("outputCropPath:"+ bitmap.Size);
                bitmap.Save(outputCropPath);
                //bitmap.Dispose();
                //graphics.Dispose();
            }

            ImageHandleV2_Opencv(bitmap, cropArea);
        }
        public static Image ImageHandleV2_Opencv(Bitmap bitmap, Rectangle cropArea)
        {
            pointsList.Clear();

            Console.WriteLine("OpenCvSharp_bitmap");

            dt1 = DateTime.Now;

            MemoryStream ms = new MemoryStream();
            bitmap.Save(ms, ImageFormat.Jpeg);  // 支持PNG、BMP等格式
            byte[] bytes = ms.ToArray();
            ms.Dispose();
            OpenCvSharp.Mat src = OpenCvSharp.Mat.FromImageData(bytes, OpenCvSharp.ImreadModes.Color);
            Console.WriteLine("src.Channels: " + src.Channels());
       
            //OpenCvSharp.Cv2.Resize(src, src, new OpenCvSharp.Size(src.Cols / scale, src.Rows / scale), (double)OpenCvSharp.InterpolationFlags.Linear);
            if (src.Empty())
            {
                Console.WriteLine("无法加载图像，请检查路径是否正确。");
                return null;
            }

            IntPtr resultPtr = do_ocr_Mat(src.CvPtr);
            if (resultPtr == IntPtr.Zero)
                return null;
            dt2 = DateTime.Now;
            Console.WriteLine("算法耗时："+(dt2-dt1).TotalMilliseconds);

            string result = Marshal.PtrToStringAnsi(resultPtr);

            byte[] rebytes = Encoding.Default.GetBytes(result);
            result = Encoding.UTF8.GetString(rebytes).Replace("end", "");


            JsonData jsonData = JsonMapper.ToObject(result);
            string finalResult = JsonMapper.ToJson(jsonData["results"]);
            Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

            List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
            configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

            for (int i = 0; i < configs.Count; i++)
            {
                Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);
                List<Point> points = new List<Point>();
                for (int j = 0; j < configs[i].box.Count; j++)
                {
                    Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                    points.Add(point);
                }
                pointsList.Add(points);
            }
            currConfigs = configs;

            convertList = ConvertPointList(pointsList, cropArea);
            LocalCompare(convertList);

            return bitmap;

        }

        public static void ImageHandleV2_Opencv_Template(Bitmap bitmap)
        {

            pointsList.Clear();
            DateTime dt1 = DateTime.Now;
            try
            {
                if (CameraReceiveThread.frameForSave == null)
                {
                    Console.WriteLine("无图像信息");
                    //return null;
                }
                MemoryStream ms = new MemoryStream();
                bitmap.Save(ms, ImageFormat.Bmp);  // 支持PNG、BMP等格式
                byte[] bytes = ms.ToArray();
                ms.Dispose();
                OpenCvSharp.Mat src = OpenCvSharp.Mat.FromImageData(bytes);
                if (src.Empty())
                {
                    Console.WriteLine("无法加载图像，请检查路径是否正确。");
                    //return null;
                }

                IntPtr resultPtr = do_ocr_Mat(src.CvPtr);
                if (resultPtr == IntPtr.Zero)
                {
                    Console.WriteLine("无法加载图像");
                    //return null;
                }
                    

                string result = Marshal.PtrToStringAnsi(resultPtr);
                DateTime dt2 = DateTime.Now;
                Console.WriteLine("间隔: " + (dt2 - dt1).Milliseconds);

                byte[] rebytes = Encoding.Default.GetBytes(result);
                result = Encoding.UTF8.GetString(rebytes).Replace("end", "");

                JsonData jsonData = JsonMapper.ToObject(result);
                string finalResult = JsonMapper.ToJson(jsonData["results"]);
                Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

                List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
                configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

                for (int i = 0; i < configs.Count; i++)
                {
                    Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);
                    List<Point> points = new List<Point>();
                    for (int j = 0; j < configs[i].box.Count; j++)
                    {
                        //Console.WriteLine("X:  "+configs[i].box[j][0]+"    Y:  " + configs[i].box[j][1]);
                        Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                        points.Add(point);
                    }
                    pointsList.Add(points);
                }
                //currConfigs.Clear();
                currConfigs = configs;
                Console.WriteLine("图片信息个数： " + pointsList.Count);

                DateTime dt3 = DateTime.Now;
                Console.WriteLine("Json解析间隔: " + (dt3 - dt2).Milliseconds);

                OCR_Form.template_Form.Template_pB.Image = RectPoints(bitmap, pointsList);
                OCR_Form.template_Form.Template_pB.SizeMode = PictureBoxSizeMode.Zoom;
                OCR_Form.template_Form.Template_pB.BackgroundImageLayout = ImageLayout.Zoom;

                Template_Form.cameraRecvBitmap = bitmap;

                Template_Form.pointsList = pointsList;

                OCR_Form.template_Form.InfoTB_01.Text = OCR_Form.template_Form.InfoTB_02.Text
                    = OCR_Form.template_Form.InfoTB_03.Text = OCR_Form.template_Form.InfoTB_04.Text
                    = OCR_Form.template_Form.InfoTB_05.Text = OCR_Form.template_Form.InfoTB_06.Text = string.Empty;
                if (currConfigs.Count >= 1)
                    OCR_Form.template_Form.InfoTB_01.Text = currConfigs[0].text;
                if (currConfigs.Count >= 2)
                    OCR_Form.template_Form.InfoTB_02.Text = currConfigs[1].text;
                if (currConfigs.Count >= 3)
                    OCR_Form.template_Form.InfoTB_03.Text = currConfigs[2].text;
                if (currConfigs.Count >= 4)
                    OCR_Form.template_Form.InfoTB_04.Text = currConfigs[3].text;
                if (currConfigs.Count >= 5)
                    OCR_Form.template_Form.InfoTB_05.Text = currConfigs[4].text;
                if (currConfigs.Count >= 6)
                    OCR_Form.template_Form.InfoTB_06.Text = currConfigs[5].text;

            }
            catch (Exception e)
            {
                throw (e);
            }

            //return bitmap;



        }

        public static void ImageHandleV2_Opencv_Refresh(string path)
        {
            //pointsList.Clear();

            Console.WriteLine("OpenCvSharp");

            OpenCvSharp.Mat src = OpenCvSharp.Cv2.ImRead(path, OpenCvSharp.ImreadModes.Color);
            if (src.Empty())
            {
                Console.WriteLine("无法加载图像，请检查路径是否正确。");
                return;
            }

            IntPtr resultPtr = do_ocr_Mat(src.CvPtr);
            //if (resultPtr == IntPtr.Zero)
            //    return;

            //string result = Marshal.PtrToStringAnsi(resultPtr);

            //byte[] rebytes = Encoding.Default.GetBytes(result);
            //result = Encoding.UTF8.GetString(rebytes).Replace("end", "");



            //JsonData jsonData = JsonMapper.ToObject(result);
            //string finalResult = JsonMapper.ToJson(jsonData["results"]);
            //Console.WriteLine("OCR Result:\n" + finalResult);

        }
        #endregion


        public static void LocalCompare(List<List<Point>> pointsList)
        {
            mainInfos.Clear();
            finalPointList.Clear();
            List<bool> inside = new List<bool>();
            bool isInsideRect = true;
            Console.WriteLine("识别框个数：" + pointsList.Count);
            foreach (var item in pointsList)
            {
                foreach (var x in item)
                {
                    bool x_Inside = int.Parse(LocalTemplateInfo.rect_X) * 2 <= x.X & x.X <= int.Parse(LocalTemplateInfo.rect_Right) * 2;
                    bool y_Inside = int.Parse(LocalTemplateInfo.rect_Y) * 2 <= x.Y & x.Y <= int.Parse(LocalTemplateInfo.rect_Bottom) * 2;
                    //Console.WriteLine("x: " + x_Inside.ToString() + "  y: " + y_Inside.ToString() + "  x&y: " + (x_Inside & y_Inside).ToString());
                    if (!(x_Inside & y_Inside))
                    {
                        isInsideRect = false;
                        break;
                    }
                    else
                    {
                        isInsideRect = true;
                    }
                }
                inside.Add(isInsideRect);
            }


            for (int i = 0; i < inside.Count; i++)
            {
                if (inside[i])
                {
                    mainInfos.Add(currConfigs[i].text);
                    finalPointList.Add(pointsList[i]);
                }
            }
            Console.WriteLine("框选信息个数：" + mainInfos.Count);
            for (int i = 0; i < mainInfos.Count; i++)
            {
                Console.WriteLine("框选信息内容" + i + "：" + mainInfos[i]);
            }
            Console.WriteLine("点位个数：" + finalPointList.Count);
        }
        //标识框 无错误对比
        public static Image RectPoints(Bitmap bitmap, List<List<Point>> pointsList)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            Pen pen = new Pen(Color.Green, 2);

            for (int i = 0; i < pointsList.Count; i++)
            {
                //graphics1.DrawLines(pen, pointsList[i].ToArray());
                //graphics1.DrawLine(pen, pointsList[i].ToArray()[0], pointsList[i].ToArray()[3]);
                graphics1.DrawPolygon(pen, pointsList[i].ToArray());
            }


            graphics1.Dispose();
            return convertedImage;
        }
        //对比区域框
        public static Image RectPoints(Bitmap bitmap, Rectangle rectangle)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            Pen pen = new Pen(Color.Red, 3);

            graphics1.DrawRectangle(pen, rectangle);

            graphics1.Dispose();
            return convertedImage;
        }
        //画外框
        public static Image RectPoints(Bitmap bitmap, List<Rectangle> rectangles)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            Pen pen = new Pen(Color.Red, 3);

            for (int i = 0; i < rectangles.Count; i++)
            {
                graphics1.DrawRectangle(pen, rectangles[i]);
            }


            graphics1.Dispose();
            return convertedImage;
        }
        public static Image RectPoints(Bitmap bitmap, List<Rectangle> rectangles,List<bool> isSame)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            Pen penRed = new Pen(Color.Red, 3);
            Pen penGreen = new Pen(Color.Green, 3);

            for (int i = 0; i < rectangles.Count; i++)
            {
                if (isSame[i])
                {
                    graphics1.DrawRectangle(penGreen, rectangles[i]);
                }
                else
                {
                    graphics1.DrawRectangle(penRed, rectangles[i]);
                }
                
            }


            graphics1.Dispose();
            return convertedImage;
        }
        //只标错误框 无错误信息
        public static Image RectPoints(Bitmap bitmap, List<List<Point>> pointsList,List<int> wrongIndex)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            Pen pen = new Pen(Color.Green, 2);
            Pen pen1 = new Pen(Color.Red, 2);

            Font font = new Font("微软雅黑", 15, FontStyle.Regular);
            Brush brush = new SolidBrush(Color.White);

            List<int> allIndex = new List<int>();
            for (int i = 0; i < pointsList.Count; i++)
            {
                allIndex.Add(i);
            }
            List<int> remainIndex = GetRemainingElements(allIndex.ToArray(), wrongIndex.ToArray()).ToList();
            for (int i = 0; i < remainIndex.Count; i++)
            {
                graphics1.DrawLines(pen, pointsList[remainIndex[i]].ToArray());
                graphics1.DrawLine(pen, pointsList[remainIndex[i]].ToArray()[0], pointsList[remainIndex[i]].ToArray()[3]);
            }
            for (int i = 0; i < wrongIndex.Count; i++)
            {
                graphics1.DrawLines(pen1, pointsList[wrongIndex[i]].ToArray());
                graphics1.DrawLine(pen1, pointsList[wrongIndex[i]].ToArray()[0], pointsList[wrongIndex[i]].ToArray()[3]);
            }



            graphics1.Dispose();
            return convertedImage;
        }
        //错误框和错误信息  传入算法信息
        public static Image RectPoints1(Bitmap bitmap, List<List<Point>> pointsList, List<int> wrongIndex, List<TemplateConfig_GPU> currConfigs)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            graphics1.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            graphics1.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            graphics1.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

            Pen pen = new Pen(Color.Green, 2);
            Pen pen1 = new Pen(Color.Red, 2);

            Font font = new Font("微软雅黑", 20, FontStyle.Regular, GraphicsUnit.Pixel);
            Brush brush1 = new SolidBrush(Color.White);
            Brush brush2 = new SolidBrush(Color.DarkRed);

            List<int> allIndex = new List<int>();
            for (int i = 0; i < pointsList.Count; i++)
            {
                allIndex.Add(i);
            }
            List<int> remainIndex = GetRemainingElements(allIndex.ToArray(), wrongIndex.ToArray()).ToList();
            for (int i = 0; i < remainIndex.Count; i++)
            {
                graphics1.DrawLines(pen, pointsList[remainIndex[i]].ToArray());
                graphics1.DrawLine(pen, pointsList[remainIndex[i]].ToArray()[0], pointsList[remainIndex[i]].ToArray()[3]);

                graphics1.DrawString(currConfigs[remainIndex[i]].text, font, brush1, pointsList[remainIndex[i]].ToArray()[0].X, pointsList[remainIndex[i]].ToArray()[0].Y - 20);
                
            }
            for (int i = 0; i < wrongIndex.Count; i++)
            {
                graphics1.DrawLines(pen1, pointsList[wrongIndex[i]].ToArray());
                graphics1.DrawLine(pen1, pointsList[wrongIndex[i]].ToArray()[0], pointsList[wrongIndex[i]].ToArray()[3]);
                graphics1.DrawString(currConfigs[wrongIndex[i]].text, font, brush2, pointsList[wrongIndex[i]].ToArray()[0].X, pointsList[wrongIndex[i]].ToArray()[0].Y - 20);

            }



            graphics1.Dispose();
            return convertedImage;
        }
        //错误框和错误信息  传入最终对比信息
        public static Image RectPoints1(Bitmap bitmap, List<List<Point>> pointsList, List<int> wrongIndex, List<string> mainInfos,List<string> wrongString)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            graphics1.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            graphics1.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            graphics1.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

            Pen penGreen = new Pen(Color.Green, 2);
            Pen penRed = new Pen(Color.Red, 2);

            Font font = new Font("微软雅黑", 20, FontStyle.Regular, GraphicsUnit.Pixel);
            Brush brushWhite = new SolidBrush(Color.White);
            Brush brushRed = new SolidBrush(Color.Red);
            Brush brushGreen = new SolidBrush(Color.Green);


            for (int i = 0; i < wrongString.Count(); i++)
            {
                //Console.WriteLine("wrongString:" + wrongString[i]);
            }
            for (int i = 0; i < mainInfos.Count(); i++)
            {
                //Console.WriteLine("mainInfos:" + mainInfos[i]);
            }


            List<string> remainString1= mainInfos.Where(x => !wrongString.Contains(x)).ToList();

            for (int i = 0; i < remainString1.Count(); i++)
            {
                //Console.WriteLine("remainString1:" + remainString1[i]);
            }

            Console.WriteLine("LocalTemplateSingleInfos_Config.finalPointsLists.Count:  "+LocalTemplateSingleInfos_Config.finalPointsLists.Count);

            //获取垂直偏移至外框下方的Rectangle合集
            int spacing = 10;
            List<List<Rectangle>> finalRects = new List<List<Rectangle>>();
            List<List<Rectangle>> finalRects2 = new List<List<Rectangle>>();
            for (int i = 0; i < LocalTemplateSingleInfos_Config.finalPointsLists.Count; i++)
            {
                finalRects.Add(OCR_Form.ConvertToRectangles(LocalTemplateSingleInfos_Config.finalPointsLists[i]));
            }

            for (int i = 0; i < finalRects.Count; i++)
            {
                finalRects2.Add(ArrangeRectangles(LocalTemplateSingleInfos_Config.rectangles[i], finalRects[i], 27));
            }


            List<List<string>> wrongStringList = new List<List<string>>();
            List<List<string>> remainStringList = new List<List<string>>();
            for (int i = 0; i < LocalTemplateSingleInfos_Config.finalPointsLists.Count; i++)
            {
                Console.WriteLine("LocalTemplateSingleInfos_Config.infosList[i].Count:" + LocalTemplateSingleInfos_Config.infosList[i].Count);

                List<string> wrongStrings = LocalTemplateSingleInfos_Config.infosList[i].ToList().Except(LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList).ToList();
                List<string> remainStrings = LocalTemplateSingleInfos_Config.localTemplateSingleInfos[i].InfoList.Where(x => LocalTemplateSingleInfos_Config.infosList[i].Contains(x)).ToList();

                for (int k = 0; k < wrongStrings.Count; k++)
                {
                    Console.WriteLine("wrongStrings_---" + wrongStrings[k]);
                }
                for (int k = 0; k < remainStrings.Count; k++)
                {
                    Console.WriteLine("remainStrings_---" + remainStrings[k]);
                }
                wrongStringList.Add(wrongStrings);
                remainStringList.Add(remainStrings);


            }
            Console.WriteLine("-----------wrongStringList.Count"+wrongStringList.Count);
            for (int i = 0; i < wrongStringList.Count; i++)
            {
                for (int j = 0; j < wrongStringList[i].Count; j++)
                {
                    Console.WriteLine("-----------wrongStringList" + wrongStringList[i][j]+"     index   "+i);
                }
            }
            Console.WriteLine("-----------remainStringList.Count" + wrongStringList.Count);
            for (int i = 0; i < remainStringList.Count; i++)
            {
                for (int j = 0; j < remainStringList[i].Count; j++)
                {
                    Console.WriteLine("-----------remainStringList" + remainStringList[i][j] + "     index   " + i);
                }
            }




            for (int i = 0; i < LocalTemplateSingleInfos_Config.finalPointsLists.Count; i++)
            {
                List<int> index_wrongStringList = FindMatchIndexes(LocalTemplateSingleInfos_Config.infosList[i], wrongStringList[i]).ToList();
                for (int j = 0; j < index_wrongStringList.Count; j++)
                {
                    Console.WriteLine("index_wrongStringList: " + index_wrongStringList[j]);
                    graphics1.DrawPolygon(penRed, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_wrongStringList[j]].ToArray());

                    StringFormat format = new StringFormat(StringFormat.GenericTypographic);
                    format.Alignment = StringAlignment.Near;
                    format.LineAlignment = StringAlignment.Near;
                    //对齐小框
                    //PointF position = new PointF(finalRects2[i][index_wrongStringList[j]].X, finalRects2[i][index_wrongStringList[j]].Y);
                    //对齐大框
                    PointF position = new PointF(LocalTemplateSingleInfos_Config.rectangles[i].X, finalRects2[i][index_wrongStringList[j]].Y);
                    SizeF textSize = graphics1.MeasureString(LocalTemplateSingleInfos_Config.infosList[i][index_wrongStringList[j]], font, position, format);
                    Console.WriteLine("textSize.Height:  " + textSize.Height);
                    RectangleF textRect = new RectangleF(position.X, position.Y, textSize.Width+10, textSize.Height);
                    graphics1.FillRectangle(brushWhite, textRect);

                    //小框上方
                    //if (LocalTemplateSingleInfos_Config.finalPointsLists[i][index_wrongStringList[j]].Count > 0)
                    //    graphics1.DrawString(LocalTemplateSingleInfos_Config.infosList[i][index_wrongStringList[j]], font, brushRed, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_wrongStringList[j]].ToArray()[0].X, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_wrongStringList[j]].ToArray()[0].Y - 20);
                    //外框右侧
                    //if (LocalTemplateSingleInfos_Config.finalPointsLists[i][index_wrongStringList[j]].Count > 0)
                    //    graphics1.DrawString(LocalTemplateSingleInfos_Config.infosList[i][index_wrongStringList[j]], font, brushRed, LocalTemplateSingleInfos_Config.rectangles[i].X + LocalTemplateSingleInfos_Config.rectangles[i].Width, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_wrongStringList[j]].ToArray()[0].Y - 20);
                    //外框下侧--对齐小框
                    //if (LocalTemplateSingleInfos_Config.finalPointsLists[i][index_wrongStringList[j]].Count > 0)
                    //      graphics1.DrawString(LocalTemplateSingleInfos_Config.infosList[i][index_wrongStringList[j]], font, brushRed, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_wrongStringList[j]].ToArray()[0].X, finalRects2[i][index_wrongStringList[j]].Y);
                    //外框下侧--对齐大框
                    if (LocalTemplateSingleInfos_Config.finalPointsLists[i][index_wrongStringList[j]].Count > 0)
                        graphics1.DrawString(LocalTemplateSingleInfos_Config.infosList[i][index_wrongStringList[j]], font, brushRed, LocalTemplateSingleInfos_Config.rectangles[i].X, finalRects2[i][index_wrongStringList[j]].Y);


                }
                List<int> index_remainStringList = FindMatchIndexes(LocalTemplateSingleInfos_Config.infosList[i], remainStringList[i]).ToList();
                if (LocalInfo.isOKRect=="1")
                {
                    for (int j = 0; j < index_remainStringList.Count; j++)
                    {
                        Console.WriteLine("index_remainStringList: " + index_remainStringList[j]);
                        graphics1.DrawPolygon(penGreen, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_remainStringList[j]].ToArray());

                        StringFormat format = new StringFormat(StringFormat.GenericTypographic);
                        format.Alignment = StringAlignment.Near;
                        format.LineAlignment = StringAlignment.Near;
                        //对齐小框
                        //PointF position = new PointF(finalRects2[i][index_remainStringList[j]].X, finalRects2[i][index_remainStringList[j]].Y);
                        //对齐大框
                        PointF position = new PointF(LocalTemplateSingleInfos_Config.rectangles[i].X, finalRects2[i][index_remainStringList[j]].Y);
                        SizeF textSize = graphics1.MeasureString(LocalTemplateSingleInfos_Config.infosList[i][index_remainStringList[j]], font, position, format);
                        Console.WriteLine("textSize.Height:  " + textSize.Height);
                        RectangleF textRect = new RectangleF(position.X, position.Y, textSize.Width + 10, textSize.Height);
                        graphics1.FillRectangle(brushWhite, textRect);

                        //if (LocalTemplateSingleInfos_Config.finalPointsLists[i][index_remainStringList[j]].Count > 0)
                        //graphics1.DrawString(LocalTemplateSingleInfos_Config.infosList[i][index_remainStringList[j]], font, brushWhite, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_remainStringList[j]].ToArray()[0].X, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_remainStringList[j]].ToArray()[0].Y - 20);
                        //if (LocalTemplateSingleInfos_Config.finalPointsLists[i][index_remainStringList[j]].Count > 0)
                        //graphics1.DrawString(LocalTemplateSingleInfos_Config.infosList[i][index_remainStringList[j]], font, brushWhite, LocalTemplateSingleInfos_Config.rectangles[i].X+ LocalTemplateSingleInfos_Config.rectangles[i].Width, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_remainStringList[j]].ToArray()[0].Y - 5);
                        //外框下侧--对齐小框
                        //if (LocalTemplateSingleInfos_Config.finalPointsLists[i][index_remainStringList[j]].Count > 0)
                        //    graphics1.DrawString(LocalTemplateSingleInfos_Config.infosList[i][index_remainStringList[j]], font, brushGreen, LocalTemplateSingleInfos_Config.finalPointsLists[i][index_remainStringList[j]].ToArray()[0].X, finalRects2[i][index_remainStringList[j]].Y);
                        //外框下侧--对齐大框
                        if (LocalTemplateSingleInfos_Config.finalPointsLists[i][index_remainStringList[j]].Count > 0)
                            graphics1.DrawString(LocalTemplateSingleInfos_Config.infosList[i][index_remainStringList[j]], font, brushGreen, LocalTemplateSingleInfos_Config.rectangles[i].X, finalRects2[i][index_remainStringList[j]].Y);

                    }
                }

            }

            graphics1.Dispose();
            return convertedImage;
        }
        static IEnumerable<int> FindMatchIndexes(List<string> source, List<string> search)
        {
            var searchSet = new HashSet<string>(search);
            return source.Select((val, idx) => new { val, idx })
                        .Where(x => searchSet.Contains(x.val))
                        .Select(x => x.idx);
        }
        //无错误框和错误信息  传入算法信息
        public static Image RectPoints1(Bitmap bitmap, List<List<Point>> pointsList, List<TemplateConfig_GPU> currConfigs)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            graphics1.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            graphics1.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            graphics1.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

            Pen pen = new Pen(Color.Green, 2);
            Font font = new Font("微软雅黑", 20, FontStyle.Regular, GraphicsUnit.Pixel);
            Brush brush1 = new SolidBrush(Color.White);
            for (int i = 0; i < pointsList.Count; i++)
            {
                //graphics1.DrawLines(pen, pointsList[i].ToArray());
                //graphics1.DrawLine(pen, pointsList[i].ToArray()[0], pointsList[i].ToArray()[3]);
                graphics1.DrawPolygon(pen, pointsList[i].ToArray());
                graphics1.DrawString(currConfigs[i].text, font, brush1, pointsList[i].ToArray()[0].X, pointsList[i].ToArray()[0].Y - 20);

            }

            graphics1.Dispose();
            return convertedImage;
        }
        //无错误框和错误信息  传入最终对比信息
        public static Image RectPoints1(Bitmap bitmap, List<List<Point>> pointsList, List<string> mainInfos)
        {
            Bitmap convertedImage = new Bitmap(
            bitmap.Width,
            bitmap.Height,
            PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(convertedImage))
            {
                g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
            }

            Graphics graphics1 = Graphics.FromImage(convertedImage);

            graphics1.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            graphics1.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            graphics1.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

            Pen pen = new Pen(Color.Green, 2);
            Font font = new Font("微软雅黑", 20, FontStyle.Regular, GraphicsUnit.Pixel);
            Brush brush1 = new SolidBrush(Color.White);
            for (int i = 0; i < pointsList.Count; i++)
            {
                graphics1.DrawLines(pen, pointsList[i].ToArray());
                graphics1.DrawLine(pen, pointsList[i].ToArray()[0], pointsList[i].ToArray()[3]);

                graphics1.DrawString(mainInfos[i], font, brush1, pointsList[i].ToArray()[0].X, pointsList[i].ToArray()[0].Y - 20);

            }



            graphics1.Dispose();
            return convertedImage;
        }
        // 提取指定索引元素
        public static string[] GetElementsByIndices(string[] source, int[] indices)
        {
            return indices.Where(i => i >= 0 && i < source.Length)
                         .Select(i => source[i])
                         .ToArray();
        }

        // 提取剩余元素（不包含指定索引）
        public static string[] GetRemainingElements(string[] source, int[] indices)
        {
            HashSet<int> indexSet = new HashSet<int>(indices);
            return Enumerable.Range(0, source.Length)
                            .Where(i => !indexSet.Contains(i))
                            .Select(i => source[i])
                            .ToArray();
        }
        public static int[] GetRemainingElements(int[] source, int[] indices)
        {
            HashSet<int> indexSet = new HashSet<int>(indices);
            return Enumerable.Range(0, source.Length)
                            .Where(i => !indexSet.Contains(i))
                            .Select(i => source[i])
                            .ToArray();
        }

        //裁剪后转换为原相对坐标
        public static List<List<Point>> ConvertPointList(List<List<Point>> pointList, Rectangle cropArea)
        {
            List<List<Point>> tempList = new List<List<Point>>();
            for (int i = 0; i < pointList.Count; i++)
            {
                tempList.Add(ConvertPointsToOriginal(pointList[i].ToArray(), cropArea).ToList());
            }

            return tempList;
        }
        //点位数组转换为原图点位
        private static Point[] ConvertPointsToOriginal(Point[] croppedPoints, Rectangle cropArea)
        {
            Point[] points = croppedPoints.Select(p => new Point(
                  p.X + cropArea.X,
                  p.Y + cropArea.Y
              )).ToArray();
            foreach (var item in points)
            {
                //Console.WriteLine("Convert: "+"x;"+item.X+"   "+"y:" + item.Y);
            }
            return points;

        }



        //转为8位像素  （使用Graphics重新画图像（包括裁剪）时，不能创建8位像素的对象，画完图后转为8位像素）
        public static Bitmap ConvertTo8bpp(Bitmap original)
        {
            // 创建目标 8bpp 位图
            Bitmap target = new Bitmap(
                original.Width,
                original.Height,
                PixelFormat.Format8bppIndexed
            );

            // 设置灰度调色板（典型 8bpp 调色板）
            ColorPalette palette = target.Palette;
            for (int i = 0; i < 256; i++)
            {
                palette.Entries[i] = Color.FromArgb(i, i, i);
            }
            target.Palette = palette;

            // 锁定位图数据
            BitmapData originalData = original.LockBits(
                new Rectangle(0, 0, original.Width, original.Height),
                ImageLockMode.ReadOnly,
                original.PixelFormat
            );

            BitmapData targetData = target.LockBits(
                new Rectangle(0, 0, target.Width, target.Height),
                ImageLockMode.WriteOnly,
                target.PixelFormat
            );

            try
            {
                // 手动转换像素（简单亮度公式）
                unsafe
                {
                    byte* targetPtr = (byte*)targetData.Scan0;
                    int* originalPtr = (int*)originalData.Scan0;

                    for (int i = 0; i < original.Height; i++)
                    {
                        for (int j = 0; j < original.Width; j++)
                        {
                            int pixel = originalPtr[j];
                            // 亮度公式：0.299*R + 0.587*G + 0.114*B
                            byte brightness = (byte)(
                                (pixel & 0xFF) * 0.114 +         // B
                                ((pixel >> 8) & 0xFF) * 0.587 +  // G
                                ((pixel >> 16) & 0xFF) * 0.299   // R
                            );
                            targetPtr[j] = brightness;
                        }
                        targetPtr += targetData.Stride;
                        originalPtr += originalData.Stride / 4;
                    }
                }
            }
            finally
            {
                original.UnlockBits(originalData);
                target.UnlockBits(targetData);
            }

            return target;
        }

        /// <summary>
        /// UTF-8格式json打印乱码 问题解决方式
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string JsonUTF8toUnicode(string jsonStr)
        {
            Regex reg = new Regex(@"(?i)\\[uU]([0-9a-f]{4})");
            var str = reg.Replace(jsonStr, delegate (Match m) { return ((char)Convert.ToInt32(m.Groups[1].Value, 16)).ToString(); });
            return str;
        }


        #region ByteArray
        //本地测试
        public static void TestImgByteArray(string path)
        {
            System.Drawing.Bitmap bitmap = new Bitmap(path);

            // 获取图片数据
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

            int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
            byte[] imageData = new byte[bmpData.Stride * bitmap.Height];

            // 拷贝数据
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, imageData, 0, imageData.Length);
            bitmap.UnlockBits(bmpData);
            for (int i = 0; i < 100; i++)
            {
                IntPtr resultPtr = do_ocr(imageData, bitmap.Width, bitmap.Height);
                if (resultPtr != IntPtr.Zero) // 确保结果不为 null
                {
                    string result = Marshal.PtrToStringAnsi(resultPtr);
                    byte[] rebytes = Encoding.Default.GetBytes(result);
                    byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
                    result = Encoding.Default.GetString(bytes, 0, bytes.Length);
                    Console.WriteLine("OCR Result:\n" + result);
                }
                else
                {
                    Console.WriteLine("OCR processing failed or instance was not created.");
                }
            }
        }
        //参数：本地路径
        public static void ImageHandleV2_ByteArray(string path)
        {
            pointsList.Clear();

            //Console.WriteLine("ImageHandleV2_ByteArray");

            Bitmap bitmap = new Bitmap(path);
            Console.WriteLine("获取图片数据");
            // 获取图片数据
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

            int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
            byte[] imageData = new byte[bmpData.Stride * bitmap.Height];
            //Console.WriteLine("拷贝数据");
            // 拷贝数据
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, imageData, 0, imageData.Length);
            bitmap.UnlockBits(bmpData);

            //Console.WriteLine("do_ocr-------------");
            dt1 = DateTime.Now;
            IntPtr resultPtr = do_ocr(imageData, bitmap.Width, bitmap.Height);
            dt2 = DateTime.Now;
            dt1_dt2_time = (dt2 - dt1).TotalMilliseconds.ToString();
            //Console.WriteLine("dt2-dt1 " + (dt2 - dt1).TotalMilliseconds);
            if (resultPtr != IntPtr.Zero) // 确保结果不为 null
            {
                string result = Marshal.PtrToStringAnsi(resultPtr);
                byte[] rebytes = Encoding.Default.GetBytes(result);
                byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
                result = Encoding.Default.GetString(bytes, 0, bytes.Length).Replace("end", "");
                //result = Encoding.UTF8.GetString(rebytes).Replace("end", "");

                //Console.WriteLine("OCR Result:\n" + result);

                JsonData jsonData = JsonMapper.ToObject(result);
                string finalResult = JsonMapper.ToJson(jsonData["results"]);
                Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

                List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
                configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

                for (int i = 0; i < configs.Count; i++)
                {
                    configs[i].text = FilterWithLINQ(configs[i].text);
                    //Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);
                    List<Point> points = new List<Point>();
                    for (int j = 0; j < configs[i].box.Count; j++)
                    {
                        Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                        points.Add(point);
                    }
                    pointsList.Add(points);
                }
                currConfigs = configs;

                //LocalCompare(pointsList);
            }
            else
            {
                Console.WriteLine("OCR processing failed or instance was not created.");
            }

            MergeChar();

        }
        //参数：bitmap
        public static void ImageHandleV2_ByteArray(Bitmap bitmap)
        {
            pointsList.Clear();

            Console.WriteLine("ImageHandleV2_ByteArray");

            // 获取图片数据
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

            int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
            byte[] imageData = new byte[bmpData.Stride * bitmap.Height];
            Console.WriteLine("bitmap.PixelFormat@@@@@@@@@@@@@@@@@" + bitmap.PixelFormat);
            Console.WriteLine("bmpData.Stride@@@@@@@@@@@@@@@@@"+ bmpData.Stride);


            // 拷贝数据
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, imageData, 0, imageData.Length);
            bitmap.UnlockBits(bmpData);

            Console.WriteLine("imageData:****************" + imageData.Length);
            dt1 = DateTime.Now;
            IntPtr resultPtr = do_ocr(imageData, bitmap.Width, bitmap.Height);
            dt2 = DateTime.Now;
            dt1_dt2_time = (dt2 - dt1).TotalMilliseconds.ToString();
            Console.WriteLine("dt2-dt1 " + (dt2 - dt1).TotalMilliseconds);
            if (resultPtr != IntPtr.Zero) // 确保结果不为 null
            {
                string result = Marshal.PtrToStringAnsi(resultPtr);
                byte[] rebytes = Encoding.Default.GetBytes(result);
                byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
                result = Encoding.Default.GetString(bytes, 0, bytes.Length).Replace("end", "");
                //result = Encoding.UTF8.GetString(rebytes).Replace("end", "");

                //Console.WriteLine("OCR Result:\n" + result);

                JsonData jsonData = JsonMapper.ToObject(result);
                string finalResult = JsonMapper.ToJson(jsonData["results"]);
                Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

                List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
                configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);
                Console.WriteLine("configs.Count" + configs.Count);

                configs = configs.Where(a => a.rec_score >= 0.3).ToList();

                Console.WriteLine("configs.Count" + configs.Count);
                for (int i = 0; i < configs.Count; i++)
                {
                    //过滤'.',汉字，字母，空格 --
                    configs[i].text = FilterWithLINQ(configs[i].text);

                    //Console.WriteLine("算法图片信息" + i + ": " + configs[i].text+ "    算法置信度"+ configs[i].rec_score);
                    List<Point> points = new List<Point>();
                    for (int j = 0; j < configs[i].box.Count; j++)
                    {
                        Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                        points.Add(point);
                    }
                    pointsList.Add(points);
                }
                currConfigs = configs;
            }
            else
            {
                Console.WriteLine("OCR processing failed or instance was not created.");
            }

            MergeChar();
        }
        //参数：bitmap  本地模板比较
        public static void ImageHandleV2_ByteArray(Bitmap bitmap, bool isCompare)
        {
            pointsList.Clear();

            Console.WriteLine("ImageHandleV2_ByteArray");

            // 获取图片数据
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

            int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
            byte[] imageData = new byte[bmpData.Stride * bitmap.Height];

            // 拷贝数据
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, imageData, 0, imageData.Length);
            bitmap.UnlockBits(bmpData);


            dt1 = DateTime.Now;
            IntPtr resultPtr = do_ocr(imageData, bitmap.Width, bitmap.Height);
            dt2 = DateTime.Now;
            dt1_dt2_time = (dt2 - dt1).TotalMilliseconds.ToString();
            Console.WriteLine("dt2-dt1 " + (dt2 - dt1).TotalMilliseconds);
            if (resultPtr != IntPtr.Zero) // 确保结果不为 null
            {
                string result = Marshal.PtrToStringAnsi(resultPtr);
                byte[] rebytes = Encoding.Default.GetBytes(result);
                byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
                result = Encoding.Default.GetString(bytes, 0, bytes.Length).Replace("end", "");
                //result = Encoding.UTF8.GetString(rebytes).Replace("end", "");

                //Console.WriteLine("OCR Result:\n" + result);

                JsonData jsonData = JsonMapper.ToObject(result);
                string finalResult = JsonMapper.ToJson(jsonData["results"]);
                Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

                List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
                configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

                for (int i = 0; i < configs.Count; i++)
                {
                    configs[i].text = FilterWithLINQ(configs[i].text);
                    Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);
                    List<Point> points = new List<Point>();
                    for (int j = 0; j < configs[i].box.Count; j++)
                    {
                        Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                        points.Add(point);
                    }
                    pointsList.Add(points);
                }
                currConfigs = configs;

                if (isCompare)
                {
                    //LocalCompare(pointsList);
                }

            }
            else
            {
                Console.WriteLine("OCR processing failed or instance was not created.");
            }

            MergeChar();
        }
        //裁剪小图
        public static void ImageHandleV2_CropImg_ByteArray(Bitmap originalImage, Rectangle cropArea, string outputCropPath = "")
        {
            DateTime dt_Crop_in = DateTime.Now;
            bool t1 = cropArea.Right > originalImage.Width;
            bool t2 = cropArea.Bottom > originalImage.Height;
            //Console.WriteLine("cropArea.X :" + cropArea.X + "  cropArea.Y :" + cropArea.Y
            //    + "  cropArea.Width :" + cropArea.Width + "  cropArea.Height :" + cropArea.Height
            //    + "  cropArea.Right :" + cropArea.Right + "  cropArea.Bottom :" + cropArea.Bottom
            //    + "  originalImage.Right :" + originalImage.Width + "  originalImage.Height :" + originalImage.Height
            //    + "  cropArea.Right > originalImage.Width：" + t1
            //    + "  cropArea.Bottom > originalImage.Height：" + t2);
            // 检查裁剪区域是否有效
            if (cropArea.X < 0 || cropArea.Y < 0 ||
                cropArea.Width <= 0 || cropArea.Height <= 0 ||
                cropArea.Right > originalImage.Width ||
                cropArea.Bottom > originalImage.Height)
            {
                Console.WriteLine("裁剪内部--裁剪区域无效");
                //return null;
                //throw new ArgumentException("Invalid crop area");
            }
            Console.WriteLine(cropArea.Size);
            // 创建目标位图
            var croppedImage = new Bitmap(cropArea.Width, cropArea.Height);
            // 创建绘图对象
            var graphics = Graphics.FromImage(croppedImage);

            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            graphics.CompositingQuality = CompositingQuality.HighQuality;
            // 绘制裁剪区域
            graphics.DrawImage(
                originalImage,
                new Rectangle(0, 0, croppedImage.Width, croppedImage.Height),
                cropArea,
                GraphicsUnit.Pixel
            );
            DateTime dt_Crop_out = DateTime.Now;
            //originalImage.Dispose();
            Bitmap bitmap = ConvertTo8bpp(croppedImage);
            if (outputCropPath != "")
            {
                //Console.WriteLine("outputCropPath:"+ bitmap.Size);
                bitmap.Save(outputCropPath);
                //bitmap.Dispose();
                //graphics.Dispose();
            }

            ImageHandleV2_ByteArray(bitmap, cropArea);
        }
        public static Image ImageHandleV2_ByteArray(Bitmap bitmap, Rectangle cropArea)
        {
            pointsList.Clear();

            Console.WriteLine("ImageHandleV2_ByteArray");

            // 获取图片数据
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

            int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
            byte[] imageData = new byte[bmpData.Stride * bitmap.Height];

            // 拷贝数据
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, imageData, 0, imageData.Length);
            bitmap.UnlockBits(bmpData);


            dt1 = DateTime.Now;
            IntPtr resultPtr = do_ocr(imageData, bitmap.Width, bitmap.Height);
            dt2 = DateTime.Now;
            dt1_dt2_time = (dt2 - dt1).TotalMilliseconds.ToString();
            Console.WriteLine("dt2-dt1 " + (dt2 - dt1).TotalMilliseconds);
            if (resultPtr != IntPtr.Zero) // 确保结果不为 null
            {
                string result = Marshal.PtrToStringAnsi(resultPtr);
                byte[] rebytes = Encoding.Default.GetBytes(result);
                byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
                result = Encoding.Default.GetString(bytes, 0, bytes.Length).Replace("end", "");

                //Console.WriteLine("OCR Result:\n" + result);

                JsonData jsonData = JsonMapper.ToObject(result);
                string finalResult = JsonMapper.ToJson(jsonData["results"]);
                Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

                List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
                configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

                for (int i = 0; i < configs.Count; i++)
                {
                    Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);
                    List<Point> points = new List<Point>();
                    for (int j = 0; j < configs[i].box.Count; j++)
                    {
                        Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                        points.Add(point);
                    }
                    pointsList.Add(points);
                }
                currConfigs = configs;
            }
            else
            {
                Console.WriteLine("OCR processing failed or instance was not created.");
            }

            convertList = ConvertPointList(pointsList, cropArea);
            LocalCompare(convertList);

            return bitmap;

        }
        //模板窗口
        public static void ImageHandleV2_Template_ByteArray(Bitmap bitmap)
        {
            try
            {
                if (CameraReceiveThread.frameForSave == null)
                {
                    Console.WriteLine("无图像信息");
                    //return null;
                }
                pointsList.Clear();

                Console.WriteLine("ImageHandleV2_ByteArray");

                // 获取图片数据
                Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

                int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
                byte[] imageData = new byte[bmpData.Stride * bitmap.Height];

                // 拷贝数据
                System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, imageData, 0, imageData.Length);
                bitmap.UnlockBits(bmpData);


                dt1 = DateTime.Now;
                IntPtr resultPtr = do_ocr(imageData, bitmap.Width, bitmap.Height);
                dt2 = DateTime.Now;

                Console.WriteLine("dt2-dt1 " + (dt2 - dt1).TotalMilliseconds);
                if (resultPtr != IntPtr.Zero) // 确保结果不为 null
                {
                    string result = Marshal.PtrToStringAnsi(resultPtr);
                    byte[] rebytes = Encoding.Default.GetBytes(result);
                    byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
                    result = Encoding.Default.GetString(bytes, 0, bytes.Length).Replace("end", "");
                    //result = Encoding.UTF8.GetString(rebytes).Replace("end", "");

                    //Console.WriteLine("OCR Result:\n" + result);

                    JsonData jsonData = JsonMapper.ToObject(result);
                    string finalResult = JsonMapper.ToJson(jsonData["results"]);
                    Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

                    List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
                    configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

                    for (int i = 0; i < configs.Count; i++)
                    {
                        Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);
                        List<Point> points = new List<Point>();
                        for (int j = 0; j < configs[i].box.Count; j++)
                        {
                            Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                            points.Add(point);
                        }
                        pointsList.Add(points);
                    }
                    currConfigs = configs;
                }
                else
                {
                    Console.WriteLine("OCR processing failed or instance was not created.");
                }
                Console.WriteLine("图片信息个数： " + pointsList.Count);

                DateTime dt3 = DateTime.Now;
                Console.WriteLine("Json解析间隔: " + (dt3 - dt2).Milliseconds);

                OCR_Form.template_Form.Template_pB.Image = RectPoints(bitmap, pointsList);
                OCR_Form.template_Form.Template_pB.SizeMode = PictureBoxSizeMode.Zoom;
                OCR_Form.template_Form.Template_pB.BackgroundImageLayout = ImageLayout.Zoom;

                Template_Form.cameraRecvBitmap = bitmap;

                Template_Form.pointsList = pointsList;

                OCR_Form.template_Form.InfoTB_01.Text = OCR_Form.template_Form.InfoTB_02.Text
                    = OCR_Form.template_Form.InfoTB_03.Text = OCR_Form.template_Form.InfoTB_04.Text
                    = OCR_Form.template_Form.InfoTB_05.Text = OCR_Form.template_Form.InfoTB_06.Text = string.Empty;
                if (currConfigs.Count >= 1)
                    OCR_Form.template_Form.InfoTB_01.Text = currConfigs[0].text;
                if (currConfigs.Count >= 2)
                    OCR_Form.template_Form.InfoTB_02.Text = currConfigs[1].text;
                if (currConfigs.Count >= 3)
                    OCR_Form.template_Form.InfoTB_03.Text = currConfigs[2].text;
                if (currConfigs.Count >= 4)
                    OCR_Form.template_Form.InfoTB_04.Text = currConfigs[3].text;
                if (currConfigs.Count >= 5)
                    OCR_Form.template_Form.InfoTB_05.Text = currConfigs[4].text;
                if (currConfigs.Count >= 6)
                    OCR_Form.template_Form.InfoTB_06.Text = currConfigs[5].text;

            }
            catch (Exception e)
            {
                throw (e);
            }

            //return bitmap;



        }

        public static void ImageHandleV2_MultiTemplate_ByteArray(Bitmap bitmap)
        {
            try
            {
                if (CameraReceiveThread.frameForSave == null)
                {
                    Console.WriteLine("无图像信息");
                    //return null;
                }
                pointsList.Clear();

                Console.WriteLine("ImageHandleV2_ByteArray");

                // 获取图片数据
                Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

                int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
                byte[] imageData = new byte[bmpData.Stride * bitmap.Height];

                // 拷贝数据
                System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, imageData, 0, imageData.Length);
                bitmap.UnlockBits(bmpData);


                dt1 = DateTime.Now;
                IntPtr resultPtr = do_ocr(imageData, bitmap.Width, bitmap.Height);
                dt2 = DateTime.Now;

                Console.WriteLine("dt2-dt1 " + (dt2 - dt1).TotalMilliseconds);
                if (resultPtr != IntPtr.Zero) // 确保结果不为 null
                {
                    string result = Marshal.PtrToStringAnsi(resultPtr);
                    byte[] rebytes = Encoding.Default.GetBytes(result);
                    byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
                    result = Encoding.Default.GetString(bytes, 0, bytes.Length).Replace("end", "");
                    //result = Encoding.UTF8.GetString(rebytes).Replace("end", "");

                    //Console.WriteLine("OCR Result:\n" + result);

                    JsonData jsonData = JsonMapper.ToObject(result);
                    string finalResult = JsonMapper.ToJson(jsonData["results"]);
                    Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

                    List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
                    configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

                    for (int i = 0; i < configs.Count; i++)
                    {
                        Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);
                        List<Point> points = new List<Point>();
                        for (int j = 0; j < configs[i].box.Count; j++)
                        {
                            Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                            points.Add(point);
                        }
                        pointsList.Add(points);
                    }
                    currConfigs = configs;
                }
                else
                {
                    Console.WriteLine("OCR processing failed or instance was not created.");
                }
                Console.WriteLine("图片信息个数： " + pointsList.Count);

                DateTime dt3 = DateTime.Now;
                Console.WriteLine("Json解析间隔: " + (dt3 - dt2).Milliseconds);

                OCR_Form.multipleRectTemplate_Form.MultiTemplatePb.Image = RectPoints1(bitmap, pointsList, currConfigs);

                MultipleRectTemplate_Form.cameraRecvBitmap = bitmap;

                MultipleRectTemplate_Form.pointsList = pointsList;

            }
            catch (Exception e)
            {
                throw (e);
            }

            //return bitmap;



        }
        //小图刷新
        public static void ImageHandleV2_Refresh_ByteArray(string path)
        {

            pointsList.Clear();
            Bitmap bitmap = new Bitmap(path);

            // 获取图片数据
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

            int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
            byte[] imageData = new byte[bmpData.Stride * bitmap.Height];

            // 拷贝数据
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, imageData, 0, imageData.Length);
            bitmap.UnlockBits(bmpData);


            dt1 = DateTime.Now;
            IntPtr resultPtr = do_ocr(imageData, bitmap.Width, bitmap.Height);
            dt2 = DateTime.Now;

            Console.WriteLine("dt2-dt1 " + (dt2 - dt1).TotalMilliseconds);
            //if (resultPtr != IntPtr.Zero) // 确保结果不为 null
            //{
            //    string result = Marshal.PtrToStringAnsi(resultPtr);
            //    byte[] rebytes = Encoding.Default.GetBytes(result);
            //    byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
            //    result = Encoding.Default.GetString(bytes, 0, bytes.Length).Replace("end", "");

            //    JsonData jsonData = JsonMapper.ToObject(result);
            //    string finalResult = JsonMapper.ToJson(jsonData["results"]);
            //    Console.WriteLine("OCR Result:\n" + finalResult);
            //}
            //else
            //{
            //    Console.WriteLine("OCR processing failed or instance was not created.");
            //}


        }
        //参数：直接传入byte数组
        public static void ImageHandleV2_ByteArray(byte[] imageData,uint width,uint height,bool iscompare)
        {
            pointsList.Clear();

            Console.WriteLine("ImageHandleV2_ByteArray");

            dt1 = DateTime.Now;
            IntPtr resultPtr = do_ocr(imageData, (int)width, (int)height);
            dt2 = DateTime.Now;
            dt1_dt2_time = (dt2 - dt1).TotalMilliseconds.ToString();
            Console.WriteLine("dt2-dt1 " + (dt2 - dt1).TotalMilliseconds);
            if (resultPtr != IntPtr.Zero) // 确保结果不为 null
            {
                string result = Marshal.PtrToStringAnsi(resultPtr);
                byte[] rebytes = Encoding.Default.GetBytes(result);
                byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, rebytes, 0, rebytes.Length);
                result = Encoding.Default.GetString(bytes, 0, bytes.Length).Replace("end", "");
                //result = Encoding.UTF8.GetString(rebytes).Replace("end", "");

                //Console.WriteLine("OCR Result:\n" + result);

                JsonData jsonData = JsonMapper.ToObject(result);
                string finalResult = JsonMapper.ToJson(jsonData["results"]);
                Console.WriteLine("OCR Result:\n" + JsonUTF8toUnicode(finalResult));

                List<TemplateConfig_GPU> configs = new List<TemplateConfig_GPU>();
                configs = JsonMapper.ToObject<List<TemplateConfig_GPU>>(finalResult);

                for (int i = 0; i < configs.Count; i++)
                {
                    //Console.WriteLine("算法图片信息" + i + ": " + configs[i].text);
                    List<Point> points = new List<Point>();
                    for (int j = 0; j < configs[i].box.Count; j++)
                    {
                        Point point = new Point(configs[i].box[j][0], configs[i].box[j][1]);
                        points.Add(point);
                    }
                    pointsList.Add(points);
                }
                currConfigs = configs;
            }
            else
            {
                Console.WriteLine("OCR processing failed or instance was not created.");
            }

            MergeChar();

            if (iscompare)
            {
                //LocalCompare(pointsList);
            }
        }
        #endregion


        public static string RemoveSymbolAndSpacesAndChineseChar(string input)
        {
            return Regex.Replace(input,@"[^a-zA-Z0-9]", "");
        }
        public static string RemoveSymbolAndSpaces(string input)
        {
            return Regex.Replace(input, @"\W", "");
        }
        public static string FilterWithLINQ(string input)
        {
            //return new string(input
            //// 1. 保留字母数字、斜杠和年月日汉字            
            //.Where(c => char.IsLetterOrDigit(c) || c == '/' ||
            //(c >= 0x4E00 && c <= 0x9FA5 && "年月日".Contains(c)))
            //// 2. 过滤字母（仅保留O/D/B/Z大小写）            
            //.Where(c => !char.IsLetter(c) || "OoDBZz".Contains(c))
            //.ToArray());

            return new string(input
            .Where(c => char.IsLetterOrDigit(c) || c == '/')
            .Where(c => c < 128) // 过滤掉非ASCII字符(包括汉字)
            .ToArray());
        }

        public static int[] CalculateDifferences(int[] arr)
        {
            if (arr == null || arr.Length < 2)
            {
                return new int[0]; 
            }

            int[] differences = new int[arr.Length - 1];
            for (int i = 0; i < arr.Length - 1; i++)
            {
                differences[i] = arr[i + 1] - arr[i];
            }

            return differences;
        }

        public static void CalculateRectangleSize(Point[] rectPoints)
        {
            // 计算宽度（取左右两边的平均值）
            int width1 = Math.Abs(rectPoints[1].X - rectPoints[0].X);
            int width2 = Math.Abs(rectPoints[2].X - rectPoints[3].X);
            int avgWidth = (width1 + width2) / 2;

            // 计算高度（取上下两边的平均值）
            int height1 = Math.Abs(rectPoints[3].Y - rectPoints[0].Y);
            int height2 = Math.Abs(rectPoints[2].Y - rectPoints[1].Y);
            int avgHeight = (height1 + height2) / 2;

            Console.WriteLine($"矩形尺寸：宽度 = {avgWidth}px, 高度 = {avgHeight}px");

        }

        public static void MergeChar()
        {
            ///同行字符合并
            List<Point> CenterPoints = new List<Point>();
            List<Point> LocationPoints = new List<Point>();
            for (int i = 0; i < pointsList.Count; i++)
            {
                int sumX = 0, sumY = 0;
                foreach (Point p in pointsList[i])
                {
                    sumX += p.X;
                    sumY += p.Y;
                }
                //Console.WriteLine("中心Point" + new Point(sumX / 4, sumY / 4));
                LocationPoints.Add(pointsList[i][0]);
                CenterPoints.Add(new Point(sumX / 4, sumY / 4));

            }

            foreach (var item in LocationPoints)
            {
                //Console.WriteLine("左上：--" + item);
            }
            //保存左上point的距离
            Dictionary<string, double> distances = CalculateDistances(LocationPoints);
            List<List<int>> combineList = new List<List<int>>();
            //距离小于55时 保存两个point对应下标 获取需要合并的两个框的下标集合combineList
            foreach (var kvp in distances)
            {
                //Console.WriteLine($"Distance between point {kvp.Key}: {kvp.Value}");
                if (kvp.Value < 55)
                {
                    List<int> temp = new List<int>();
                    for (int i = 0; i < kvp.Key.Split(',').Length; i++)
                    {
                        temp.Add(int.Parse(kvp.Key.Split(',')[i]));
                    }
                    combineList.Add(temp);
                }
            }
            foreach (var item in combineList)
            {
                foreach (var item1 in item)
                {
                    //Console.WriteLine("item1--int" + item1);
                }
            }
            //将需要合并的框中重复的下标先合并 例如{1，2}和{2，3}合并为{1，2，3}
            List<List<int>> mergeIndexList = MergeStringsWithIndices(combineList);
            //所有需要合并的下标集合--根据该集合获取需要替换的算法信息以及剩余信息
            List<int> mergeSumIndexList = new List<int>();
            foreach (var item in mergeIndexList)
            {
                foreach (var item1 in item)
                {
                    mergeSumIndexList.Add(item1);
                }
            }
            //替换的合并信息
            List<TemplateConfig_GPU> combineConfigs = new List<TemplateConfig_GPU>();
            //无需替换的剩余信息
            List<TemplateConfig_GPU> nocombineConfigs = new List<TemplateConfig_GPU>(currConfigs);
            mergeSumIndexList.Sort((a, b) => b.CompareTo(a));
            foreach (int index in mergeSumIndexList)
            {
                if (index >= 0 && index < currConfigs.Count)
                {
                    combineConfigs.Add(currConfigs[index]);
                    nocombineConfigs.RemoveAt(index);
                }
            }
            foreach (var item in combineConfigs)
            {
                //Console.WriteLine("combineConfigs:----" + item.text);
            }
            foreach (var item in nocombineConfigs)
            {
                //Console.WriteLine("nocombineConfigs:----" + item.text);
            }
            //获取最终需要替换的文字信息部分
            List<string> mergedStrings = new List<string>();
            foreach (var indices in mergeIndexList)
            {
                if (indices.Count == 0) continue;

                string mergedString = currConfigs[indices[0]].text;

                for (int i = 1; i < indices.Count; i++)
                {
                    mergedString += currConfigs[indices[i]].text;
                }

                mergedStrings.Add(mergedString);
            }
            foreach (var item in mergedStrings)
            {
                //Console.WriteLine("mergedStrings:---" + item);
            }

            //将需要合并信息的point集合合并
            List<List<Point>> MergePoints_TEMP = MergePoints(pointsList, mergeIndexList);
            // 输出结果
            foreach (var list in MergePoints_TEMP)
            {
                //Console.WriteLine("Merged List:");
                foreach (var point in list)
                {
                    //Console.WriteLine($"({point.X}, {point.Y})");
                }
            }

            //获取包含所有合并point集合的矩形的顶点集合
            List<List<Point>> finalRect = new List<List<Point>>();
            foreach (var item in MergePoints_TEMP)
            {
                finalRect.Add(GetBoundingBoxPoints(item));
            }
            foreach (var item in finalRect)
            {
                //Console.WriteLine("Bounding Box Points:");
                foreach (Point point in item)
                {
                    //Console.WriteLine($"({point.X}, {point.Y})");
                }
            }

            //最终合并point集合转换为box形式
            List<List<List<int>>> finalBoxes = new List<List<List<int>>>();
            foreach (var item in finalRect)
            {
                finalBoxes.Add(ConvertPointsToLists(item));
            }
            //Console.WriteLine("finalBoxes.Count:----" + finalBoxes.Count);
            foreach (var item in finalBoxes)
            {
                foreach (var list in item)
                {
                    //Console.WriteLine($"[{string.Join(", ", list)}]");
                }
            }
            //Console.WriteLine("mergedStrings:----" + mergedStrings.Count);

            //获取不需合并的point信息集合
            List<List<Point>> nocombinePointList = new List<List<Point>>(pointsList);
            foreach (var index in mergeSumIndexList)
            {
                nocombinePointList.RemoveAt(index);
            }

            //最终合并后的point信息和文字信息转为算法信息格式，并和之前不需合并的信息整合为新的算法信息
            List<TemplateConfig_GPU> finalTemplateConfig_GPU = new List<TemplateConfig_GPU>();
            for (int i = 0; i < mergedStrings.Count; i++)
            {
                TemplateConfig_GPU templateConfig_GPU = new TemplateConfig_GPU
                {
                    box = finalBoxes[i],
                    text = mergedStrings[i],
                    rec_score = 1,
                    cls_score = 1,
                    cls_label = 1
                };
                finalTemplateConfig_GPU.Add(templateConfig_GPU);
            }
            for (int i = 0; i < finalTemplateConfig_GPU.Count; i++)
            {
                nocombineConfigs.Add(finalTemplateConfig_GPU[i]);
            }
            foreach (var item in finalRect)
            {
                nocombinePointList.Add(item);
            }
            currConfigs = nocombineConfigs;
            pointsList = nocombinePointList;
        }
        //计算两个point的距离
        public static double CalculateDistances(Point p1,Point p2)
        {
            return Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2));
        }
        //记录所有左上两个点的距离
        static Dictionary<string,double> CalculateDistances(List<Point> points)
        {
            var distances = new Dictionary<string, double>();
            for (int i = 0; i<points.Count; i++)        
            {
                for (int j = i + 1; j<points.Count; j++)
                {
                    if (Math.Abs(points[i].Y - points[j].Y) <= 5)
                    {
                        string key = $"{i},{j}";
                        double distance = CalculateDistances(points[i], points[j]);
                        distances.Add(key, distance);
                    }

                }
            }

            return distances;
        }
        //将重复下标合并  获取最终需要的下标组合
        static List<List<int>> MergeStringsWithIndices(List<List<int>> indicesLists)
        {
            // Step 1: Merge overlapping lists
            var mergedIndexSets = new HashSet<HashSet<int>>();

            foreach (var indices in indicesLists)
            {
                var currentSet = new HashSet<int>(indices);
                bool isMerged = false;

                for (int i = 0; i < mergedIndexSets.Count; i++)
                {
                    var set = mergedIndexSets.ElementAt(i);
                    if (set.Overlaps(currentSet))
                    {
                        set.UnionWith(currentSet);
                        isMerged = true;
                        break;
                    }
                }

                if (!isMerged)
                {
                    mergedIndexSets.Add(currentSet);
                }
            }

            // Step 2: Convert sets back to lists and sort them
            var mergedIndexLists = mergedIndexSets.Select(set => set.ToList()).ToList();
            foreach (var list in mergedIndexLists)
            {
                list.Sort();
            }
            //Console.WriteLine("mergedIndexLists.Count:--"+mergedIndexLists.Count);
            foreach (var item in mergedIndexLists)
            {
                foreach (var item1 in item)
                {
                    //Console.WriteLine("MergeStringsWithIndices: "+item1);
                }
            }
            return mergedIndexLists;
        }
        //将需要合并信息的point集合合并--通过所有的点位集合pointlist和获取的需要合并的下标集合
        public static List<List<Point>> MergePoints(List<List<Point>> A, List<List<int>> B)
        {
            List<List<Point>> mergedLists = new List<List<Point>>();

            foreach (var indices in B)
            {
                List<Point> mergedList = new List<Point>();
                foreach (var index in indices)
                {
                    if (index >= 0 && index < A.Count)
                    {
                        mergedList.AddRange(A[index]);
                    }
                }
                mergedLists.Add(mergedList);
            }

            return mergedLists;
        }
        //获取包含point集合中所有point 的矩形 的四个顶点point
        static List<Point> GetBoundingBoxPoints(List<Point> points)
        {
            if (points == null || points.Count == 0)
            {
                throw new ArgumentException("The list of points cannot be null or empty.");
            }

            int minX = int.MaxValue;
            int minY = int.MaxValue;
            int maxX = int.MinValue;
            int maxY = int.MinValue;

            foreach (Point point in points)
            {
                if (point.X < minX) minX = point.X;
                if (point.Y < minY) minY = point.Y;
                if (point.X > maxX) maxX = point.X;
                if (point.Y > maxY) maxY = point.Y;
            }

            // 返回矩形的四个顶点
            return new List<Point>
        {
            new Point(minX, minY), // 左上角
            new Point(maxX, minY), // 右上角
            new Point(maxX, maxY), // 右下角
            new Point(minX, maxY)  // 左下角
        };
        }
        //由于获取到的算法信息中所有point信息是以box集合形式（List<List<int>>），所以将最终获得框转换为box形式
        static List<List<int>> ConvertPointsToLists(List<Point> points)
        {
            List<List<int>> result = new List<List<int>>();

            foreach (var point in points)
            {
                result.Add(new List<int> { point.X, point.Y });
            }

            return result;
        }


        public static List<Rectangle> ArrangeRectangles(Rectangle mainRect, List<Rectangle> smallRects, int spacing = 10)
        {
            // 计算所有小矩形总高度
            int totalHeight = 0;
            foreach (var rect in smallRects)
            {
                totalHeight += rect.Height;
            }

            // 确定起始Y坐标（大矩形底部 + 间距）
            int startY = mainRect.Bottom + spacing;

            List<Rectangle> result = new List<Rectangle>();

            // 创建每个小矩形的新实例
            int currentY = startY;
            foreach (var rect in smallRects)
            {
                result.Add(new Rectangle(
                    x: rect.X,
                    y: currentY,
                    width: rect.Width,
                    height: rect.Height
                ));
                //根据小框间隔排列
                //currentY += rect.Height + spacing;
                //固定间隔
                //currentY += 27 + spacing;
                currentY += spacing;
            }

            return result;
        }
    }
}
